﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SLWCFPowerShellOutput
{
    public partial class Page : UserControl
    {
        private bool _front = true;
        private Storyboard _sb = new Storyboard();
        private TimeSpan _tsLastFrame = new TimeSpan();
        public Page()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
            this.btnRotate.Click += new RoutedEventHandler(btnRotate_Click);
            this.btnExecute.Click += new RoutedEventHandler(btnExecute_Click);
        }

        void btnRotate_Click(object sender, RoutedEventArgs e)
        {
            if (_front)
            {
                _sb.Pause();
                _sb.AutoReverse = false;
                _sb.Begin();
                _front = false;
            }
            else
            {
                _sb.Pause();
                _sb.AutoReverse = true;
                _sb.Seek(_tsLastFrame);
                _sb.Resume();

                _front = true;
            }
        }

        void btnExecute_Click(object sender, RoutedEventArgs e)
        {
            txtPoshResult.Text = "";
            PoshboardWCFRef.Service1Client webService = new SLWCFPowerShellOutput.PoshboardWCFRef.Service1Client();            
            webService.ExecutePowerShellCodeCompleted += new EventHandler<SLWCFPowerShellOutput.PoshboardWCFRef.ExecutePowerShellCodeCompletedEventArgs>(webService_ExecutePowerShellCodeCompleted);
            webService.ExecutePowerShellCodeAsync(txtPoshCode.Text.ToString());

            if (_front)
            {
                //_sb.Pause();
                //_sb.AutoReverse = false;
                //_sb.Begin();
                //_front = false;
            }
            else
            {
                _sb.Pause();
                _sb.AutoReverse = true;
                _sb.Seek(_tsLastFrame);
                _sb.Resume();

                _front = true;
            }
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            TransformGroup transforms = new TransformGroup();
            ScaleTransform scale = new ScaleTransform();

            transforms.Children.Add(scale);
            this.screens.RenderTransform = transforms;

            Storyboard sbForward = new Storyboard();
            AnimateFlip(_sb, scale, out _tsLastFrame);

            this.LayoutRoot.Resources.Add("Animation", _sb);
        }

        void webService_ExecutePowerShellCodeCompleted(object sender, SLWCFPowerShellOutput.PoshboardWCFRef.ExecutePowerShellCodeCompletedEventArgs e)
        {
            txtPoshResult.Text = e.Result;           
        }

        
        private static KeySpline DefineKeySpline(double cp1X, double cp1Y, double cp2X, double cp2Y)
        {
            KeySpline ksStart = new KeySpline();
            ksStart.ControlPoint1 = new Point(cp1X, cp1Y);
            ksStart.ControlPoint2 = new Point(cp2X, cp2Y);
            return ksStart;
        }

        private TimeSpan AnimateFlip(Storyboard sb, ScaleTransform scale, out TimeSpan tsLastFrame)
        {
            double speed = 4;
            double flipRotation = 0;
            double flipped = 2;
            tsLastFrame = new TimeSpan();
            TimeSpan tsSideFlipped = new TimeSpan();

            int frames = 1;
            DoubleAnimationUsingKeyFrames daX = new DoubleAnimationUsingKeyFrames();
            tsLastFrame = new TimeSpan();
            while (flipRotation != flipped * 180)
            {
                flipRotation += speed;
                double flipRadian = flipRotation * (Math.PI / 180);
                double size = Math.Cos(flipRadian);
                double scalar = (1 / (1 / size));

                DiscreteDoubleKeyFrame ddkfX = new DiscreteDoubleKeyFrame();
                ddkfX.Value = (size * scalar);

                tsLastFrame = TimeSpan.FromMilliseconds(frames * 7);

                //the first time we flip to negative capture the tsLastFrame so we know when we will need to
                //visualize the flip side
                flipped = (size < 0) ? +1 : +0;
                if (flipped == 1 && tsSideFlipped.Ticks == 0)
                {
                    tsSideFlipped = tsLastFrame;
                }

                ddkfX.KeyTime = KeyTime.FromTimeSpan(tsLastFrame);

                //add the DiscreteDoubleKeyFrame to the DoubleAnimationUsingKeyFrames
                daX.KeyFrames.Add(ddkfX);

                flipRotation %= 360;
                frames++;
            }

            Storyboard.SetTarget(daX, scale);
            Storyboard.SetTargetProperty(daX, new PropertyPath("(ScaleX)"));
            sb.Children.Add(daX);

            VisualizeSide(sb, tsSideFlipped, 0, TimeSpan.FromMilliseconds((tsSideFlipped.Milliseconds + 100)), back.Opacity, this.back);
            VisualizeSide(sb, TimeSpan.FromMilliseconds((tsSideFlipped.Milliseconds - 100)), front.Opacity, tsSideFlipped, 0, this.front);
            back.Opacity = 0;
            return tsLastFrame;
        }

        private void VisualizeSide(Storyboard sb, TimeSpan tsStart, double opacityStart, TimeSpan tsEnd, double opacityEnd, UIElement side)
        {
            DoubleAnimationUsingKeyFrames daOpacity = new DoubleAnimationUsingKeyFrames();
            SplineDoubleKeyFrame sdkfStart = new SplineDoubleKeyFrame();
            sdkfStart.Value = opacityStart;
            sdkfStart.KeyTime = tsStart;
            sdkfStart.KeySpline = DefineKeySpline(0, 0, 1, 1);
            daOpacity.KeyFrames.Add(sdkfStart);

            SplineDoubleKeyFrame sdkfEnd = new SplineDoubleKeyFrame();
            sdkfEnd.Value = opacityEnd;
            sdkfEnd.KeyTime = tsEnd;
            sdkfEnd.KeySpline = DefineKeySpline(0, 0, 1, 1);
            daOpacity.KeyFrames.Add(sdkfEnd);

            Storyboard.SetTarget(daOpacity, side);
            Storyboard.SetTargetProperty(daOpacity, new PropertyPath("(UIElement.Opacity)"));

            sb.Children.Add(daOpacity);
        }
    }
}
